﻿namespace UnityEditor
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using UnityEngine;

    internal class PopupList : EditorWindow
    {
        private const float frameWidth = 1f;
        private const float gizmoRightAlign = 23f;
        private const float iconRightAlign = 64f;
        private const float k_LineHeight = 16f;
        private const float k_Margin = 10f;
        private const float k_TextFieldHeight = 16f;
        private const float listElementHeight = 18f;
        private string m_CustomLabel = string.Empty;
        private string m_CustomLabelPrefix = string.Empty;
        private InputData m_Data;
        private Gravity m_Gravity;
        private Vector2 m_ScreenPos;
        private Vector2 m_ScrollPosition;
        private static float s_LastClosedTime;
        private static Vector2 s_LastPos = Vector2.zero;
        private static PopupList s_PopupList = null;
        private static EditorGUI.RecycledTextEditor s_RecycledEditor = new EditorGUI.RecycledTextEditor();
        private static Styles s_Styles;
        private static int s_TextFieldHash = "ObjectBrowserPopUpTextField".GetHashCode();
        private const float scrollBarWidth = 14f;

        private PopupList()
        {
            base.hideFlags = HideFlags.DontSave;
        }

        private void Cancel()
        {
            base.Close();
            GUI.changed = true;
            GUIUtility.ExitGUI();
        }

        internal static void CloseList()
        {
            if (s_PopupList != null)
            {
                s_PopupList.Close();
            }
        }

        private void DrawCustomTextField()
        {
            bool flag4;
            if (!this.m_Data.m_AllowCustom)
            {
                return;
            }
            Event current = Event.current;
            bool flag = true;
            bool flag2 = false;
            bool flag3 = false;
            string customLabel = this.m_CustomLabel;
            if (current.type == EventType.KeyDown)
            {
                KeyCode keyCode = current.keyCode;
                switch (keyCode)
                {
                    case KeyCode.Backspace:
                        flag = false;
                        this.m_Data.ResetSelectedCompletion();
                        goto Label_01E8;

                    case KeyCode.Tab:
                    case KeyCode.Return:
                        break;

                    default:
                        switch (keyCode)
                        {
                            case KeyCode.UpArrow:
                                this.m_Data.SelectCompletion(-1);
                                flag2 = true;
                                current.Use();
                                goto Label_01E8;

                            case KeyCode.DownArrow:
                                this.m_Data.SelectCompletion(1);
                                flag2 = true;
                                current.Use();
                                goto Label_01E8;

                            case KeyCode.None:
                                if ((current.character == ' ') || (current.character == ','))
                                {
                                    current.Use();
                                }
                                goto Label_01E8;

                            default:
                                if ((keyCode != KeyCode.Space) && (keyCode != KeyCode.Comma))
                                {
                                    goto Label_01E8;
                                }
                                break;
                        }
                        break;
                }
                if (this.m_CustomLabel != string.Empty)
                {
                    if (this.m_Data.m_OnSelectCallback != null)
                    {
                        this.m_Data.m_OnSelectCallback(this.m_Data.NewOrMatchingElement(this.m_CustomLabel));
                    }
                    if (this.m_Data.GetFilteredCount(this.m_CustomLabelPrefix) <= 2)
                    {
                        flag2 = true;
                        this.m_CustomLabelPrefix = string.Empty;
                        flag = false;
                        this.m_Data.ResetSelectedCompletion();
                        customLabel = this.m_CustomLabelPrefix;
                        this.m_CustomLabel = this.m_CustomLabelPrefix;
                        s_RecycledEditor.content.text = this.m_CustomLabelPrefix;
                        EditorGUI.s_OriginalText = this.m_CustomLabelPrefix;
                    }
                    if (this.m_Data.m_CloseOnSelection || (current.keyCode == KeyCode.Return))
                    {
                        flag3 = true;
                    }
                    else
                    {
                        this.ResetWindowSize();
                    }
                }
                current.Use();
            }
        Label_01E8:
            flag4 = false;
            Rect position = new Rect(5f, (this.m_Gravity != Gravity.Top) ? ((base.position.height - 16f) - 5f) : 5f, (base.position.width - 10f) - 14f, 16f);
            int id = EditorGUI.GetControlID(s_TextFieldHash, FocusType.Keyboard, position);
            if (GUIUtility.keyboardControl == 0)
            {
                GUIUtility.keyboardControl = id;
            }
            this.m_CustomLabel = EditorGUI.DoTextField(s_RecycledEditor, id, position, this.m_CustomLabel, s_Styles.customTextField, null, out flag4, false, false, false);
            Rect rect2 = position;
            rect2.x += position.width;
            rect2.width = 14f;
            if (GUI.Button(rect2, GUIContent.none, !(this.m_CustomLabel != string.Empty) ? s_Styles.customTextFieldCancelButtonEmpty : s_Styles.customTextFieldCancelButton) && (this.m_CustomLabel != string.Empty))
            {
                this.m_CustomLabelPrefix = string.Empty;
                customLabel = this.m_CustomLabelPrefix;
                this.m_CustomLabel = this.m_CustomLabelPrefix;
                s_RecycledEditor.content.text = this.m_CustomLabelPrefix;
                EditorGUI.s_OriginalText = this.m_CustomLabelPrefix;
                s_RecycledEditor.pos = 0;
                s_RecycledEditor.selectPos = 0;
                flag = false;
                this.m_Data.ResetSelectedCompletion();
                this.ResetWindowSize();
            }
            if ((this.m_CustomLabel != customLabel) || flag2)
            {
                this.m_CustomLabelPrefix = ((s_RecycledEditor.pos >= this.m_CustomLabel.Length) || (s_RecycledEditor.pos < 0)) ? this.m_CustomLabel : this.m_CustomLabel.Substring(0, s_RecycledEditor.pos);
                this.ResetWindowSize();
                if (flag)
                {
                    string completion = this.m_Data.GetCompletion(this.m_CustomLabelPrefix);
                    if (completion != string.Empty)
                    {
                        int pos = s_RecycledEditor.pos;
                        int length = completion.Length;
                        this.m_CustomLabel = completion;
                        s_RecycledEditor.content.text = this.m_CustomLabel;
                        EditorGUI.s_OriginalText = this.m_CustomLabel;
                        s_RecycledEditor.pos = pos;
                        s_RecycledEditor.selectPos = length;
                    }
                }
            }
            if (flag3)
            {
                base.Close();
            }
        }

        private void DrawList()
        {
            Event current = Event.current;
            int num = -1;
            IEnumerator<ListElement> enumerator = this.m_Data.GetFilteredList(this.m_CustomLabelPrefix).GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    ListElement element = enumerator.Current;
                    num++;
                    Rect position = new Rect(0f, (10f + (num * 16f)) + (((this.m_Gravity != Gravity.Top) || !this.m_Data.m_AllowCustom) ? 0f : 16f), base.position.width, 16f);
                    switch (current.type)
                    {
                        case EventType.MouseDown:
                            if ((Event.current.button == 0) && position.Contains(Event.current.mousePosition))
                            {
                                if (this.m_Data.m_OnSelectCallback != null)
                                {
                                    this.m_Data.m_OnSelectCallback(element);
                                }
                                current.Use();
                                if (this.m_Data.m_CloseOnSelection)
                                {
                                    base.Close();
                                }
                            }
                            break;

                        case EventType.Repaint:
                        {
                            GUIStyle label = s_Styles.label;
                            label.padding.left = 10;
                            bool selected = element.selected;
                            bool hasFocus = base.m_Parent.hasFocus;
                            bool isHover = false;
                            bool isActive = selected;
                            GUIContent content = element.m_Content;
                            label.Draw(position, content, isHover, isActive, selected, hasFocus);
                            if (element.text.Equals(this.m_CustomLabel, StringComparison.OrdinalIgnoreCase))
                            {
                                position.x++;
                                position.width -= 2f;
                                s_Styles.autocompleteOverlay.Draw(position, false, false, false, false);
                            }
                            break;
                        }
                    }
                }
            }
            finally
            {
                if (enumerator == null)
                {
                }
                enumerator.Dispose();
            }
        }

        private float GetWindowHeight()
        {
            return (((this.m_Data.GetFilteredCount(this.m_CustomLabelPrefix) * 16f) + 20f) + (!this.m_Data.m_AllowCustom ? 0f : 16f));
        }

        private float GetWindowWidth()
        {
            return 150f;
        }

        private void Init(Vector2 pos, InputData inputData, Gravity gravity)
        {
            this.m_Data = inputData;
            this.m_Data.ResetScores();
            this.m_Data.ResetSelectedCompletion();
            this.m_Gravity = gravity;
            this.m_ScreenPos = GUIUtility.GUIToScreenPoint(pos);
            Rect buttonRect = new Rect(this.m_ScreenPos.x, this.m_ScreenPos.y - 16f, 16f, 16f);
            base.ShowAsDropDown(buttonRect, new Vector2(this.GetWindowWidth(), this.GetWindowHeight()));
        }

        private void OnDisable()
        {
            this.m_Data.ResetScores();
            s_LastClosedTime = Time.realtimeSinceStartup;
            s_PopupList = null;
        }

        private void OnEnable()
        {
        }

        internal void OnGUI()
        {
            Event current = Event.current;
            if (current.type != EventType.Layout)
            {
                if (s_Styles == null)
                {
                    s_Styles = new Styles();
                }
                if ((current.type == EventType.KeyDown) && (current.keyCode == KeyCode.Escape))
                {
                    this.Cancel();
                }
                if (this.m_Gravity == Gravity.Bottom)
                {
                    this.DrawList();
                    this.DrawCustomTextField();
                }
                else
                {
                    this.DrawCustomTextField();
                    this.DrawList();
                }
                if (current.type == EventType.Repaint)
                {
                    s_Styles.background.Draw(new Rect(0f, 0f, base.position.width, base.position.height), false, false, false, false);
                }
            }
        }

        private void ResetWindowSize()
        {
            float windowHeight = this.GetWindowHeight();
            Rect rect = new Rect {
                x = this.m_ScreenPos.x,
                y = this.m_ScreenPos.y - ((this.m_Gravity != Gravity.Bottom) ? 0f : windowHeight),
                width = this.GetWindowWidth(),
                height = windowHeight
            };
            float minimumHeight = windowHeight;
            base.position = base.m_Parent.window.FitPopupWindowRectToScreen(rect, minimumHeight);
            base.minSize = new Vector2(base.position.width, base.position.height);
            base.maxSize = new Vector2(base.position.width, base.position.height);
        }

        internal static bool ShowAtPosition(Vector2 pos, InputData inputData, Gravity gravity)
        {
            bool flag = Mathf.Abs((float) (Time.realtimeSinceStartup - s_LastClosedTime)) < 0.05f;
            Vector2 vector = s_LastPos - pos;
            if ((vector.magnitude <= 0.1f) && flag)
            {
                return false;
            }
            Event.current.Use();
            if (s_PopupList == null)
            {
                s_PopupList = ScriptableObject.CreateInstance<PopupList>();
                s_PopupList.hideFlags = HideFlags.HideAndDontSave;
            }
            s_LastPos = pos;
            s_PopupList.Init(pos, inputData, gravity);
            return true;
        }

        internal static bool isOpen
        {
            get
            {
                return (s_PopupList != null);
            }
        }

        public enum Gravity
        {
            Top,
            Bottom
        }

        public class InputData
        {
            [CompilerGenerated]
            private static Func<PopupList.ListElement, float> <>f__am$cache9;
            [CompilerGenerated]
            private static Func<PopupList.ListElement, string> <>f__am$cacheA;
            [CompilerGenerated]
            private static Func<PopupList.ListElement, string> <>f__am$cacheB;
            public bool m_AllowCustom;
            public bool m_CloseOnSelection;
            private string m_LastCompletion = string.Empty;
            private string m_LastPrefix = string.Empty;
            public List<PopupList.ListElement> m_ListElements = new List<PopupList.ListElement>();
            public int m_MaxCount;
            public PopupList.OnSelectCallback m_OnSelectCallback;
            private int m_SelectedCompletion;
            public bool m_SortAlphabetically;

            private IEnumerable<PopupList.ListElement> BuildQuery(string prefix)
            {
                <BuildQuery>c__AnonStoreyE ye = new <BuildQuery>c__AnonStoreyE {
                    prefix = prefix
                };
                if (ye.prefix == string.Empty)
                {
                    return this.m_ListElements;
                }
                return Enumerable.Where<PopupList.ListElement>(this.m_ListElements, new Func<PopupList.ListElement, bool>(ye.<>m__13));
            }

            public void DeselectAll()
            {
                foreach (PopupList.ListElement element in this.m_ListElements)
                {
                    element.selected = false;
                }
            }

            public string GetCompletion(string prefix)
            {
                if (<>f__am$cacheB == null)
                {
                    <>f__am$cacheB = element => element.text;
                }
                IEnumerable<string> source = Enumerable.Select<PopupList.ListElement, string>(this.GetFilteredList(prefix), <>f__am$cacheB);
                this.m_LastPrefix = prefix;
                if ((this.m_LastCompletion != string.Empty) && this.m_LastCompletion.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
                {
                    this.m_SelectedCompletion = Enumerable.TakeWhile<string>(source, (Func<string, bool>) (element => (element != this.m_LastCompletion))).Count<string>();
                    return this.m_LastCompletion;
                }
                return (this.m_LastCompletion = source.Skip<string>(this.m_SelectedCompletion).DefaultIfEmpty<string>(string.Empty).FirstOrDefault<string>());
            }

            public int GetFilteredCount(string prefix)
            {
                IEnumerable<PopupList.ListElement> source = this.BuildQuery(prefix);
                if (this.m_MaxCount > 0)
                {
                    source = source.Take<PopupList.ListElement>(this.m_MaxCount);
                }
                return source.Count<PopupList.ListElement>();
            }

            public IEnumerable<PopupList.ListElement> GetFilteredList(string prefix)
            {
                IEnumerable<PopupList.ListElement> enumerable = this.BuildQuery(prefix);
                if (this.m_MaxCount > 0)
                {
                    if (<>f__am$cache9 == null)
                    {
                        <>f__am$cache9 = element => element.filterScore;
                    }
                    enumerable = Enumerable.OrderByDescending<PopupList.ListElement, float>(enumerable, <>f__am$cache9).Take<PopupList.ListElement>(this.m_MaxCount);
                }
                if (!this.m_SortAlphabetically)
                {
                    return enumerable;
                }
                if (<>f__am$cacheA == null)
                {
                    <>f__am$cacheA = element => element.text.ToLower();
                }
                return Enumerable.OrderBy<PopupList.ListElement, string>(enumerable, <>f__am$cacheA);
            }

            public PopupList.ListElement NewOrMatchingElement(string label)
            {
                <NewOrMatchingElement>c__AnonStoreyF yf = new <NewOrMatchingElement>c__AnonStoreyF {
                    label = label
                };
                this.m_LastCompletion = string.Empty;
                PopupList.ListElement item = Enumerable.Where<PopupList.ListElement>(this.m_ListElements, new Func<PopupList.ListElement, bool>(yf.<>m__16)).DefaultIfEmpty<PopupList.ListElement>(null).FirstOrDefault<PopupList.ListElement>();
                if (item == null)
                {
                    item = new PopupList.ListElement(yf.label, false, -1f);
                    this.m_ListElements.Add(item);
                }
                return item;
            }

            public void ResetScores()
            {
                foreach (PopupList.ListElement element in this.m_ListElements)
                {
                    element.ResetScores();
                }
            }

            public void ResetSelectedCompletion()
            {
                this.m_SelectedCompletion = -1;
                this.m_LastCompletion = string.Empty;
            }

            public void SelectCompletion(int change)
            {
                int num = this.GetFilteredList(this.m_LastPrefix).Count<PopupList.ListElement>();
                if ((this.m_SelectedCompletion == -1) && (change < 0))
                {
                    this.m_SelectedCompletion = num;
                }
                this.m_SelectedCompletion = (num <= 0) ? 0 : ((this.m_SelectedCompletion + change) % num);
                if (this.m_SelectedCompletion < 0)
                {
                    this.m_SelectedCompletion += num;
                }
                this.m_LastCompletion = string.Empty;
            }

            [CompilerGenerated]
            private sealed class <BuildQuery>c__AnonStoreyE
            {
                internal string prefix;

                internal bool <>m__13(PopupList.ListElement element)
                {
                    return element.m_Content.text.StartsWith(this.prefix, StringComparison.OrdinalIgnoreCase);
                }
            }

            [CompilerGenerated]
            private sealed class <NewOrMatchingElement>c__AnonStoreyF
            {
                internal string label;

                internal bool <>m__16(PopupList.ListElement element)
                {
                    return element.text.Equals(this.label, StringComparison.OrdinalIgnoreCase);
                }
            }
        }

        public class ListElement
        {
            public GUIContent m_Content;
            private float m_FilterScore;
            private bool m_Selected;
            private bool m_WasSelected;

            public ListElement(string text)
            {
                this.m_Content = new GUIContent(text);
                this.m_Selected = false;
                this.filterScore = 0f;
            }

            public ListElement(string text, bool selected)
            {
                this.m_Content = new GUIContent(text);
                this.m_Selected = selected;
                this.filterScore = 0f;
            }

            public ListElement(string text, bool selected, float score)
            {
                this.m_Content = new GUIContent(text);
                if (!string.IsNullOrEmpty(this.m_Content.text))
                {
                    char[] chArray = this.m_Content.text.ToCharArray();
                    chArray[0] = char.ToUpper(chArray[0]);
                    this.m_Content.text = new string(chArray);
                }
                this.m_Selected = selected;
                this.filterScore = score;
            }

            public void ResetScores()
            {
                this.m_WasSelected = this.m_Selected;
            }

            public float filterScore
            {
                get
                {
                    return (!this.m_WasSelected ? this.m_FilterScore : float.MaxValue);
                }
                set
                {
                    this.m_FilterScore = value;
                    this.m_WasSelected = this.m_Selected;
                }
            }

            public bool selected
            {
                get
                {
                    return this.m_Selected;
                }
                set
                {
                    this.m_Selected = value;
                    if (this.m_Selected)
                    {
                        this.m_WasSelected = true;
                    }
                }
            }

            public string text
            {
                get
                {
                    return this.m_Content.text;
                }
                set
                {
                    this.m_Content.text = value;
                }
            }
        }

        public delegate void OnSelectCallback(PopupList.ListElement element);

        private class Styles
        {
            public GUIStyle autocompleteOverlay;
            public GUIStyle background = "grey_border";
            public GUIStyle customTextField = new GUIStyle(EditorStyles.toolbarSearchField);
            public GUIStyle customTextFieldCancelButton = new GUIStyle(EditorStyles.toolbarSearchFieldCancelButton);
            public GUIStyle customTextFieldCancelButtonEmpty = new GUIStyle(EditorStyles.toolbarSearchFieldCancelButtonEmpty);
            public GUIStyle label = "PR Label";

            public Styles()
            {
                this.autocompleteOverlay = new GUIStyle(this.background);
            }
        }
    }
}

